package com.jichangxiu.generator.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.jichangxiu.common.annotation.Dynamic;
import com.jichangxiu.common.exception.ServiceException;
import com.jichangxiu.common.utils.ConvertUtils;
import com.jichangxiu.generator.entity.bo.GenCategoryBo;
import com.jichangxiu.generator.entity.dto.add.AddGenCategory;
import com.jichangxiu.generator.entity.dto.edit.EditGenCategory;
import com.jichangxiu.generator.entity.dto.query.QueryGenCategory;
import com.jichangxiu.generator.entity.po.GenCategory;
import com.jichangxiu.generator.entity.po.GenTemplate;
import com.jichangxiu.generator.entity.vo.GenCategoryVo;
import com.jichangxiu.generator.entity.vo.GenTemplateVo;
import com.jichangxiu.generator.mapper.GenCategoryMapper;
import com.jichangxiu.generator.service.GenCategoryService;
import com.jichangxiu.generator.service.GenTemplateService;
import com.jichangxiu.framework.utils.SecurityUtils;
import com.jichangxiu.framework.utils.NoUtils;
import com.jichangxiu.common.entity.bo.ValidateBos;
import com.jichangxiu.framework.service.impl.BaseServiceImpl;
import com.jichangxiu.framework.utils.ValidateUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * GenCategoryServiceImpl:
 *
 * @author JiChangXiu
 * @create 2024-06-30 13:30:59
 */
@Service
public class GenCategoryServiceImpl extends BaseServiceImpl<GenCategoryMapper, GenCategory, GenCategoryVo> implements GenCategoryService {

    @Resource
    private GenTemplateService genTemplateService;

    /**
     * 新增生成分类
     *
     * @param addGenCategory 新增生成分类视图对象
     * @return 是否成功
     */
    @Dynamic
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(AddGenCategory addGenCategory) {
        return getBaseMapper().insert(addAndEditValidBo(ConvertUtils.convert(addGenCategory, GenCategoryBo.class))) > 0;
    }

    /**
     * 单（多）选删除生成分类
     *
     * @param idList 生成分类主键列表
     * @return 是否成功
     */
    @Dynamic
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean del(List<String> idList) {
        return getBaseMapper().deleteBatchIds(delValid(idList)) > 0;
    }

    /**
     * 修改生成分类
     *
     * @param editGenCategory 修改生成分类视图对象
     * @return 是否成功
     */
    @Dynamic
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean edit(EditGenCategory editGenCategory) {
        return getBaseMapper().updateById(addAndEditValidBo(ConvertUtils.convert(editGenCategory, GenCategoryBo.class))) > 0;
    }

    /**
     * 根据主键查询生成分类
     *
     * @param id       生成分类主键
     * @param isExtend 是否扩展
     * @return 生成分类详情
     */
    @Dynamic
    @Override
    public GenCategoryVo info(@NotBlank(message = "主键不能为空") String id, Boolean isExtend) {
        GenCategoryVo genCategoryVo = getBaseMapper().selectJoinOne(GenCategoryVo.class, buildQueryWrapper(QueryGenCategory.builder().id(id).build()));
        if (Boolean.TRUE.equals(isExtend) && ObjectUtil.isNotEmpty(genCategoryVo))
            genCategoryVo = renderGenCategoryVoList(ListUtil.toList(genCategoryVo)).get(0);
        return genCategoryVo;
    }

    /**
     * （可分页）查询生成分类列表
     *
     * @param queryGenCategory 查询视图对象
     * @return （分页）生成分类列表
     */
    @Dynamic
    @Override
    public Page<GenCategoryVo> lists(QueryGenCategory queryGenCategory) {
        Page<GenCategoryVo> genCategoryVoPage = getBaseMapper().selectJoinPage(startPage(), GenCategoryVo.class, buildQueryWrapper(queryGenCategory));
        if (Boolean.TRUE.equals(queryGenCategory.getIsExtend()))
            genCategoryVoPage.setRecords(renderGenCategoryVoList(genCategoryVoPage.getRecords()));
        return genCategoryVoPage;
    }

    /**
     * 新增 / 修改 前校验
     *
     * @param genCategoryBo 校验用业务对象
     * @return 数据库操作对象
     */
    public GenCategory addAndEditValidBo(GenCategoryBo genCategoryBo) {
        GenCategory genCategory = ConvertUtils.convert(genCategoryBo, GenCategory.class);
        if (ObjectUtil.isNull(genCategory))
            throw new ServiceException("待校验对象为空");
        List<ValidateBos> validateBosList = Stream.of(
                ValidateUtils.createNeValidateBos(ValidateUtils.createValidateBo(GenCategory::getId, genCategory.getId(), "主键")),
                ValidateUtils.createOrEqValidateBos(
                        ValidateUtils.createValidateBo(GenCategory::getNo, genCategory.getNo(), "编码"),
                        ValidateUtils.createValidateBo(GenCategory::getCode, genCategory.getCode(), "标识"),
                        ValidateUtils.createValidateBo(GenCategory::getName, genCategory.getName(), "名称"),
                        ValidateUtils.createValidateBo(GenCategory::getRemark, genCategory.getRemark(), "备注"))
        ).collect(Collectors.toList());
        // 唯一校验
        ValidateUtils.uniqueValidate(this::countWrapper, validateBosList);
        if (StrUtil.isEmpty(genCategory.getId())) {
            // 新增
            genCategory.setNo(NoUtils.createNo(SecurityUtils.getTenantId(), "category"));
            genCategory.setTenantId(SecurityUtils.getTenantId());
            return genCategory;
        } else {
            // 修改
            GenCategory dbGenCategory = getById(genCategory.getId());
            if (!genCategory.getEnabled().equals(dbGenCategory.getEnabled()) && genTemplateService.count(new LambdaQueryWrapper<GenTemplate>().in(GenTemplate::getCategoryId, genCategory.getId())) != 0)
                throw new ServiceException("该分类下存在模板，不能修改状态");
            BeanUtil.copyProperties(genCategory, dbGenCategory, true);
            return dbGenCategory;
        }
    }

    /**
     * 删除前校验
     *
     * @param idList 主键列表
     * @return 主键列表
     */
    public List<String> delValid(List<String> idList) {
        if (ObjectUtil.isNull(idList))
            throw new ServiceException("待校验主键列表为空");
        if (genTemplateService.count(new LambdaQueryWrapper<GenTemplate>().in(GenTemplate::getCategoryId, idList)) != 0)
            throw new ServiceException("尚有分类下存在模板，不能删除");
        return idList;
    }

    /**
     * 渲染视图
     *
     * @param genCategoryVoList 视图列表
     * @return 渲染后的视图列表
     */
    public List<GenCategoryVo> renderGenCategoryVoList(List<GenCategoryVo> genCategoryVoList) {
        if (ObjectUtil.isNotEmpty(genCategoryVoList)) {
            // todo 扩展信息填入
            List<GenTemplateVo> genTemplateVoList = genTemplateService.voList(new LambdaQueryWrapper<GenTemplate>().in(GenTemplate::getCategoryId, genCategoryVoList.stream().map(GenCategoryVo::getId).collect(Collectors.toList())));
            if (ObjectUtil.isNotEmpty(genTemplateVoList)) {
                genCategoryVoList.forEach(genCategoryVo -> genCategoryVo.setGenTemplateVoList(genTemplateVoList.stream().filter(genTemplateVo -> genTemplateVo.getCategoryId().equals(genCategoryVo.getId())).collect(Collectors.toList())));
            }
        }
        return genCategoryVoList;
    }

    /**
     * 构建查询条件
     *
     * @param queryGenCategory 查询用业务对象
     * @return 查询条件
     */
    public MPJLambdaWrapper<GenCategory> buildQueryWrapper(QueryGenCategory queryGenCategory) {
        MPJLambdaWrapper<GenCategory> lambdaQueryWrapper = new MPJLambdaWrapper<GenCategory>().selectAll(GenCategory.class);
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(queryGenCategory.getId()), GenCategory::getId, queryGenCategory.getId());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(queryGenCategory.getNo()), GenCategory::getNo, queryGenCategory.getNo());
        lambdaQueryWrapper.like(StrUtil.isNotEmpty(queryGenCategory.getCode()), GenCategory::getCode, queryGenCategory.getCode());
        lambdaQueryWrapper.like(StrUtil.isNotEmpty(queryGenCategory.getName()), GenCategory::getName, queryGenCategory.getName());
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(queryGenCategory.getSort()), GenCategory::getSort, queryGenCategory.getSort());
        lambdaQueryWrapper.like(StrUtil.isNotEmpty(queryGenCategory.getRemark()), GenCategory::getRemark, queryGenCategory.getRemark());
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(queryGenCategory.getEnabled()), GenCategory::getEnabled, queryGenCategory.getEnabled());
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(queryGenCategory.getEnabledBy()), GenCategory::getEnabledBy, queryGenCategory.getEnabledBy());
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(queryGenCategory.getEnabledTime()), GenCategory::getEnabledTime, queryGenCategory.getEnabledTime());
        return lambdaQueryWrapper;
    }

}